﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Linq.Expressions;

namespace PersonaLibrary.Validation
{
    public class ValidEntity
    {
        public object SelectedValue { set; get; }

        public object SelectedKey { set; get; }
    }

    public class ValidationItem<T> : INotifyPropertyChanged
    {
        private string _validationValue = "";
        private bool _isValid;
        private List<string> _parentCandidates = new List<string>();
        private List<ValidEntity> _collection;
        private bool _moreThenOneCand;
        private RelayCommand _validateCommand;

        public bool IsValid
        {
            set
            {
                _isValid = value;
                risePropertyChanged("IsValid");
            }
            get
            {
                return _isValid;
            }
        }

        public string ValidationValue
        {
            set
            {
                _validationValue = value;
                risePropertyChanged("ValidationValue");
                if (!_parentCandidates.Contains(value)) IsValid = false;
                else
                {
                    IsValid = true;
                    MoreThenOneCand = false;
                }
            }
            get
            {
                return _validationValue;
            }
        }

        public ValidEntity Value
        {
            get
            {
                if (_collection == null) 
                    if (EntitySelector != null) 
                        _collection = Source.Where(ValidExpression).Select(EntitySelector).ToList();
                return _collection.FirstOrDefault(x => x.SelectedKey.ToString() == _validationValue);
            }
        }

        public List<string> Candidates
        {
            set
            {
                _parentCandidates = value;
                risePropertyChanged("Candidates");
            }
            get
            {
                return _parentCandidates;
            }
        }

        public bool MoreThenOneCand
        {
            set
            {
                _moreThenOneCand = value;
                risePropertyChanged("MoreThenOneCand");
            }
            get
            {
                return _moreThenOneCand;
            }
        }

        public IQueryable<T> Source { set; get; }

        public Expression<Func<T, string>> Selector { set; get; }

        public Expression<Func<T, ValidEntity>> EntitySelector { set; get; }

        public Expression<Func<T, bool>> ValidExpression { set; get; }

        public RelayCommand ValidateCommand
        {
            get
            {
                if (_validateCommand == null) _validateCommand = new RelayCommand(param => validate(), param => Source != null);
                return _validateCommand;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void risePropertyChanged(string name)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        private void validate()
        {
			if(ValidExpression == null)
				return;

            if (Source.Where(ValidExpression).Count() == 1)
            {
                Candidates = Source.Where(ValidExpression).Select(Selector).ToList();
                if(EntitySelector != null) _collection = Source.Where(ValidExpression).Select(EntitySelector).ToList();
                ValidationValue = Candidates[0];
                IsValid = true;
            }
            else if (Source.Where(ValidExpression).Count() > 1)
            {
                Candidates = Source.Where(ValidExpression).Select(Selector).ToList();
                if (EntitySelector != null) _collection = Source.Where(ValidExpression).Select(EntitySelector).ToList();
                if (Candidates.Contains(_validationValue)) IsValid = true;
                MoreThenOneCand = true;
            }
        }
    }
}
